package com.open.utils;

import org.yaml.snakeyaml.Yaml;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Objects;

public class YamlUtil {

    /**
     * YAML文件反序列化（只解析配置文件名称和对象名称相同）
     *
     * @param clazz    配置类类型
     * @param fileName 配置文件名
     * @param <T>      配置类型
     * @return 配置对象
     */
    public static <T> T loadConfig(Class<T> clazz, String fileName) {
        Yaml yaml = new Yaml();

        // 获取YAML文件的输入流
        InputStream inputStream = YamlUtil.class.getClassLoader().getResourceAsStream(fileName);
        if (inputStream == null) {
            throw new RuntimeException("配置文件未找到: " + fileName);
        }

        Reader reader = new InputStreamReader(inputStream);

        // 解析YAML文件为Map结构
        Map<String, Map<String, Object>> config = yaml.load(reader);
        T instance = null;

        try {
            // 创建指定类型的对象实例
            instance = clazz.getDeclaredConstructor().newInstance();

            // 反射机制，遍历YAML文件中的配置
            for (Map.Entry<String, Map<String, Object>> entity : config.entrySet()) {
                String entityKey = entity.getKey();
                Map<String, Object> entityValue = entity.getValue();
                //只解析配置文件名称和对象名称相同
                if (Objects.equals(entityKey, clazz.getSimpleName())) {
                    paddingObject(clazz, entityValue, instance);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("解析配置文件或创建对象时出错", e);
        }

        return instance;
    }

    /**
     * YAML文件反序列化（支持多级路径配置）
     *
     * @param clazz     配置类类型
     * @param fileName  配置文件名
     * @param yamlPath  YAML配置路径（如："spring.datasource"）
     * @param <T>       配置类型
     * @return 配置对象
     */
    public static <T> T loadConfig(Class<T> clazz, String fileName, String yamlPath) {
        Yaml yaml = new Yaml();

        InputStream inputStream = YamlUtil.class.getClassLoader().getResourceAsStream(fileName);
        if (inputStream == null) {
            throw new RuntimeException("配置文件未找到: " + fileName);
        }

        try (Reader reader = new InputStreamReader(inputStream)) {
            // 加载完整配置树
            Map<String, Object> fullConfig = yaml.load(reader);

            // 根据路径定位配置节点
            Map<String, Object> targetConfig = getConfigByPath(fullConfig, yamlPath);

            // 创建配置对象实例
            T instance = clazz.getDeclaredConstructor().newInstance();

            // 反射注入字段值
            paddingObject(clazz, targetConfig, instance);
            return instance;
        } catch (Exception e) {
            throw new RuntimeException("解析配置文件失败", e);
        }
    }

    /**
     * 填充对象
     * @param clazz
     * @param entityValue
     * @param instance
     * @param <T>
     * @throws IllegalAccessException
     */
    private static <T> void paddingObject(Class<T> clazz, Map<String, Object> entityValue, T instance) throws IllegalAccessException {
        for (Map.Entry<String, Object> attribute : entityValue.entrySet()) {
            String fieldName = convertYamlKeyToFieldName(attribute.getKey());
            Object value = attribute.getValue();

            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                field.set(instance, convertValue(field.getType(), value));
            } catch (NoSuchFieldException e) {
                System.err.println("警告: 配置字段 " + attribute.getKey() + " 在类 " + clazz.getName() + " 中不存在");
            }
        }
    }

    /**
     * 根据路径获取配置节点
     */
    private static Map<String, Object> getConfigByPath(Map<String, Object> config, String yamlPath) {
        String[] pathSegments = yamlPath.split("\\.");
        Map<String, Object> current = config;

        for (String segment : pathSegments) {
            Object node = current.get(segment);
            if (node instanceof Map) {
                current = (Map<String, Object>) node;
            } else {
                throw new RuntimeException("无效配置路径: " + yamlPath);
            }
        }
        return current;
    }

    /**
     * 转换YAML键到Java字段名（如：driver-class-name -> driverClassName）
     */
    private static String convertYamlKeyToFieldName(String yamlKey) {
        String[] parts = yamlKey.split("-");
        StringBuilder fieldName = new StringBuilder(parts[0]);
        for (int i = 1; i < parts.length; i++) {
            fieldName.append(parts[i].substring(0, 1).toUpperCase())
                    .append(parts[i].substring(1));
        }
        return fieldName.toString();
    }

    /**
     * 类型转换处理
     */
    private static Object convertValue(Class<?> targetType, Object value) {
        if (value == null) return null;
        if (targetType.isAssignableFrom(value.getClass())) {
            return value;
        }
        // 添加更多类型转换逻辑（根据实际需要扩展）
        if (targetType == Integer.class || targetType == int.class) {
            return Integer.parseInt(value.toString());
        }
        if (targetType == Boolean.class || targetType == boolean.class) {
            return Boolean.parseBoolean(value.toString());
        }
        return value.toString();
    }
}
